package com.urbane.gateway.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * JWT 工具类（仅用于解析和验证，不生成 Token）
 * 说明：Token 由 auth-service 生成，网关只负责验证
 * <p> <a href="https://github.com/jwtk/jjwt">jjwt 工具官网</a>
 * <p> <a href="https://www.jwt.io/">jwt.io</a>
 * 密钥建议：使用环境变量或 Vault 管理，不要硬编码
 */
@Component
public class JwtUtil {

    // 从 application.yml 加载密钥（生产环境请使用 KMS 或环境变量）
    @Value("${jwt.secret}")
    private String secret;

    // Token 默认过期时间（单位：毫秒），这里设为 2 小时
    private static final long EXPIRATION_TIME = 2 * 60 * 60 * 1000L;

    /**
     * 从 Token 中提取用户 ID
     *
     * @param token JWT 字符串
     * @return 用户 ID（Long 类型），如果解析失败抛出异常
     * 参考 Reading a JWT <a href="https://github.com/jwtk/jjwt?tab=readme-ov-file#reading-a-jwt">...</a>
     */
    public static Long getUserIdFromToken(String token) {
        Claims claims = Jwts.parser()
                .verifyWith(getSigningKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();

        Object userIdObj = claims.get("userId");
        if (userIdObj == null) {
            throw new IllegalArgumentException("Token 中未包含 userId");
        }
        return Long.parseLong(userIdObj.toString());
    }

    /**
     * 从 Token 中提取角色列表（逗号分隔字符串）
     *
     * @param token JWT 字符串
     * @return 角色字符串，如 "USER,ADMIN"
     */
    public static String getRolesFromToken(String token) {
        Claims claims = Jwts.parser()
                .verifyWith(getSigningKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();

        Object rolesObj = claims.get("roles");
        if (rolesObj == null) {
            return "";
        }
        return rolesObj.toString();
    }

    /**
     * 校验 Token 是否过期
     *
     * @param token JWT 字符串
     * @return true 表示已过期
     */
    public boolean isTokenExpired(String token) {
        Claims claims = Jwts.parser()
                .verifyWith(getSigningKey())
                .build()
                .parseSignedClaims(token)
                .getPayload();

        Date expiration = claims.getExpiration();
        return expiration.before(new Date());
    }

    /**
     * 生成签名密钥（从 Base64 编码字符串还原）
     */
    private static SecretKey getSigningKey() {
        // 我们需要一个签名密钥，因此我们将仅为此示例创建一个签名密钥.
        // 通常，密钥将从您的应用程序配置中读取.
        SecretKey key = Jwts.SIG.HS256.key().build();

        byte[] keyBytes = Decoders.BASE64.decode(secret);
        return Keys.hmacShaKeyFor(keyBytes);
    }
}
